package com.g2room.file.excel;

import org.apache.poi.hssf.usermodel.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * @param <T>
 * @author vn0gv3u
 */
public class ExportExcel<T> {
    /**
     * 这是一个通用的方法，利用了JAVA的反射机制，可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出到指定IO设备上
     *
     * @param title   表格标题名
     * @param content 需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。
     * @param path    输出文件路径
     */
    public void exportExcel(String title, List<T> content, String path)
            throws ReflectiveOperationException, IOException {
        exportExcel(title, content, new FileOutputStream(new File(path)));
    }

    /**
     * 这是一个通用的方法，利用了JAVA的反射机制，可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出到指定IO设备上
     *
     * @param title   表格标题名
     * @param content 需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。
     * @param output  与输出设备关联的流对象，可以将EXCEL文档导出到本地文件或者网络中
     */
    public void exportExcel(String title, List<T> content, OutputStream output) throws ReflectiveOperationException, IOException {
        // 声明一个工作薄
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 生成一个表格
        HSSFSheet sheet = workbook.createSheet(title);
        // 设置表格默认列宽度为20个字节
        sheet.setDefaultColumnWidth((short) 20);

        if (content == null || content.size() == 0)
            return;
        T tempT = content.get(0);
        Field[] fieldsList = tempT.getClass().getDeclaredFields();
        List<String> fieldNames = new ArrayList<>();
        HSSFRow row = sheet.createRow(0);
        int i = 0;
        // 获取字段注解的表头
        for (Field field : fieldsList) {
            ExcelField excelField = field.getAnnotation(ExcelField.class);
            if (null != excelField) {
                field.setAccessible(true);
                fieldNames.add(field.getName());
                // 产生表格标题行
                HSSFCell cell = row.createCell(i);
                cell.setCellValue(new HSSFRichTextString(excelField.name()));
                i++;
            }
        }
        // 遍历集合数据，产生数据行
        Iterator<T> it = content.iterator();
        int rowIdx = 0;
        while (it.hasNext()) {
            rowIdx++;
            row = sheet.createRow(rowIdx);
            T t = (T) it.next();
            int cellIdx;
            for (Field field : fieldsList) {
                cellIdx = fieldNames.indexOf(field.getName());
                if (cellIdx < 0) {
                    continue;
                }
                HSSFCell cell = row.createCell(cellIdx);
                String fieldName = field.getName();
                String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                Class tCls = t.getClass();
                Method getMethod = tCls.getMethod(getMethodName, new Class[]{});
                Object value = getMethod.invoke(t, new Object[]{});
                // 判断值的类型后进行强制类型转换
                String textValue;
                if (value == null) {
                    cell.setCellValue("");
                }
                if (value instanceof Integer) {
                    int intValue = (Integer) value;
                    cell.setCellValue(intValue);
                } else if (value instanceof Float) {
                    float fValue = (Float) value;
                    cell.setCellValue(fValue);
                } else if (value instanceof Double) {
                    double dValue = (Double) value;
                    cell.setCellValue(dValue);
                } else if (value instanceof Long) {
                    long longValue = (Long) value;
                    cell.setCellValue(longValue);
                } else if (value instanceof Date) {
                    Date date = (Date) value;
                    textValue = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(date);
                    cell.setCellValue(textValue);
                } else {
                    // 其它数据类型都当作字符串简单处理
                    textValue = value == null ? "" : value.toString();
                    cell.setCellValue(textValue);
                }
            }
        }
        workbook.write(output);
    }
}